﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using WMPLib;

// Song attributes: http://msdn.microsoft.com/en-us/library/bb248412(VS.85).aspx
// Podcast feed: http://www.podcast411.com/howto_1.html
// Itunes: http://www.apple.com/itunes/whatson/podcasts/specs.html

namespace ScottLane.MediaFeeder.ObjectModel
{
    /// <summary>
    /// Represents an audio song in the Media Player library.
    /// </summary>
    public class Song
    {
        #region Properties

        private string _songID;

        /// <summary>
        /// Gets the song identifier.
        /// </summary>
        public string SongID
        {
            get { return _songID; }
        }

        private string _title;

        /// <summary>
        /// Gets the song title.
        /// </summary>
        public string Title
        {
            get { return _title; }
        }

        private string _artist;

        /// <summary>
        /// Gets the song artist.
        /// </summary>
        public string Artist
        {
            get { return _artist; }
        }

        private string _albumTitle;

        /// <summary>
        /// Gets the album title.
        /// </summary>
        public string AlbumTitle
        {
            get { return _albumTitle; }
        }

        private string _albumArtist;

        /// <summary>
        /// Gets the album artist.
        /// </summary>
        public string AlbumArtist
        {
            get { return _albumArtist; }
        }

        private string _trackNumber;

        /// <summary>
        /// Gets the track number.
        /// </summary>
        public string TrackNumber
        {
            get { return _trackNumber; }
        }

        private int _year;

        /// <summary>
        /// Gets the year the song was released.
        /// </summary>
        public int Year
        {
            get { return _year; }
        }

        private string _genre;

        /// <summary>
        /// Gets the song genre.
        /// </summary>
        public string Genre
        {
            get { return _genre; }
        }

        private TimeSpan _duration;

        /// <summary>
        /// Gets the song duration.
        /// </summary>
        public TimeSpan Duration
        {
            get { return _duration; }
        }

        private DateTime _dateAdded;

        /// <summary>
        /// Gets the date the song was added to the library.
        /// </summary>
        public DateTime DateAdded
        {
            get { return _dateAdded; }
        }

        private string _fileName;

        /// <summary>
        /// Gets the song file name.
        /// </summary>
        public string FileName
        {
            get { return _fileName; }
        }

        private long _fileSize;

        /// <summary>
        /// Gets the song file size in bytes.
        /// </summary>
        public long FileSize
        {
            get { return _fileSize; }
        }

        private string _fileType;

        /// <summary>
        /// Gets the song file name extension.
        /// </summary>
        public string FileType
        {
            get { return _fileType; }
        }

        #endregion

        /// <summary>
        /// Initializes a new instance of the Song class with the specified identifier.
        /// </summary>
        /// <param name="songID">The song identifier.</param>
        /// <returns>The Song instance.</returns>
        public Song(string songID)
        {
            IWMPMediaCollection library = MediaPlayer.Instance.mediaCollection;
            IWMPPlaylist playlist = library.getByAttribute(MediaItemAttibute.TrackingID, songID);
            
            if (playlist.count != 1)
            {
                throw new ArgumentException("The specified song does not exist.", "songID");
            }

            IWMPMedia item = playlist.get_Item(0);
            ParseFromItem(item);
        }

        /// <summary>
        /// Initializes a new instance of the Song class from a Media Player media item.
        /// </summary>
        /// <param name="item">The media item.</param>
        internal Song(IWMPMedia item)
        {
            ParseFromItem(item);        
        }

        /// <summary>
        /// Parses the Song details from a Media Player item.
        /// </summary>
        /// <param name="item">The item.</param>
        private void ParseFromItem(IWMPMedia item)
        {
            _songID = item.getItemInfo(MediaItemAttibute.TrackingID);

            if (item.getItemInfo(MediaItemAttibute.Author) != string.Empty)
            {
                _artist = item.getItemInfo(MediaItemAttibute.Author);
            }
            if (item.getItemInfo(MediaItemAttibute.Title) != string.Empty)
            {
                _title = item.getItemInfo(MediaItemAttibute.Title);
            }
            if (item.getItemInfo(MediaItemAttibute.AlbumArtist) != string.Empty)
            {
                _albumArtist = item.getItemInfo(MediaItemAttibute.AlbumArtist);
            }
            if (item.getItemInfo(MediaItemAttibute.AlbumTitle) != string.Empty)
            {
                _albumTitle = item.getItemInfo(MediaItemAttibute.AlbumTitle);
            }
            if (item.getItemInfo(MediaItemAttibute.Year) != string.Empty)
            {
                _year = int.Parse(item.getItemInfo(MediaItemAttibute.Year));
            }
            if (item.getItemInfo(MediaItemAttibute.Genre) != string.Empty)
            {
                _genre = item.getItemInfo(MediaItemAttibute.Genre);
            }
            if (item.getItemInfo(MediaItemAttibute.TrackNumber) != string.Empty)
            {
                _trackNumber = item.getItemInfo(MediaItemAttibute.TrackNumber);
            }
            if (item.getItemInfo(MediaItemAttibute.Duration) != string.Empty)
            {
                _duration = TimeSpan.FromSeconds((double)decimal.Round(decimal.Parse(item.getItemInfo(MediaItemAttibute.Duration)), 0));
            }
            if (item.sourceURL != string.Empty)
            {
                _fileName = item.sourceURL;
            }
            if (item.getItemInfo(MediaItemAttibute.FileType) != string.Empty)
            {
                _fileType = item.getItemInfo(MediaItemAttibute.FileType);
            }
            if (item.getItemInfo(MediaItemAttibute.FileSize) != string.Empty)
            {
                _fileSize = long.Parse(item.getItemInfo(MediaItemAttibute.FileSize));
            }
            if (item.getItemInfo(MediaItemAttibute.AcquisitionTime) != string.Empty)
            {
                _dateAdded = DateTime.Parse(item.getItemInfo(MediaItemAttibute.AcquisitionTime));
            }
        }

        /// <summary>
        /// Plays the song in Media Center.
        /// </summary>
        public void Play()
        {
            string mediaCenterFileName = @"C:\Program Files\Windows Media Player\wmplayer.exe"; // todo

            Process executable = new Process();
            executable.StartInfo.FileName = mediaCenterFileName;
            executable.StartInfo.WorkingDirectory = new FileInfo(mediaCenterFileName).DirectoryName;
            executable.StartInfo.Arguments = _fileName;
            executable.StartInfo.UseShellExecute = true;
            executable.Start();
        }

        /// <summary>
        /// Checks whether a song with the specified identifier exists in the Media Player library.
        /// </summary>
        /// <param name="songID">The song identifier.</param>
        /// <returns>True if the song exists, false otherwise.</returns>
        public static bool Exists(string songID)
        {
            IWMPMediaCollection library = MediaPlayer.Instance.mediaCollection;
            IWMPPlaylist playlist = library.getByAttribute(MediaItemAttibute.TrackingID, songID);

            if (playlist.count <= 0)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// Searches the Media Player library for songs containing the specified attributes.
        /// </summary>
        /// <param name="title">The song title.</param>
        /// <param name="artist">The song artist.</param>
        /// <param name="albumTitle">The album title.</param>
        /// <param name="albumArtist">The album artist.</param>
        /// <param name="genre">The genre.</param>
        /// <param name="startIndex">The index of the first song to include in the results.</param>
        /// <param name="maxResults">The maximum number of songs to return.</param>
        /// <param name="order">The result sort order.</param>
        /// <returns>The songs.</returns>
        public static List<Song> Search(string title, string artist, string albumTitle, string albumArtist, string genre, int startIndex, int maxResults, SongSortOrder order)
        {
            IWMPMediaCollection2 library = (IWMPMediaCollection2)MediaPlayer.Instance.mediaCollection;
            IWMPQuery query = library.createQuery();

            query.addCondition(MediaItemAttibute.Title, QueryOperator.NotEquals, string.Empty);

            if (title != null)
            {
                query.addCondition(MediaItemAttibute.Title, QueryOperator.Contains, title);
            }
            if (artist != null)
            {
                query.addCondition(MediaItemAttibute.Author, QueryOperator.Contains, artist);
            }
            if (albumTitle != null)
            {
                query.addCondition(MediaItemAttibute.AlbumTitle, QueryOperator.Contains, albumTitle);
            }
            if (albumArtist != null)
            {
                query.addCondition(MediaItemAttibute.AlbumArtist, QueryOperator.Contains, albumArtist);
            }
            if (genre != null)
            {
                query.addCondition(MediaItemAttibute.Genre, QueryOperator.Contains, genre);
            }

            string sortOrder = null;

            if (order == SongSortOrder.Title)
            {
                sortOrder = MediaItemAttibute.Title;
            }
            else if (order == SongSortOrder.Artist)
            {
                sortOrder = MediaItemAttibute.Artist;
            }
            else if (order == SongSortOrder.AlbumArtist)
            {
                sortOrder = MediaItemAttibute.AlbumArtist;
            }
            else if (order == SongSortOrder.AlbumTitle)
            {
                sortOrder = MediaItemAttibute.AlbumTitle;
            }
            else if (order == SongSortOrder.Year)
            {
                sortOrder = MediaItemAttibute.Year;
            }
            else if (order == SongSortOrder.Genre)
            {
                sortOrder = MediaItemAttibute.Genre;
            }

            IWMPPlaylist playlist = library.getPlaylistByQuery(query, MediaType.Audio, sortOrder, true);
            List<Song> songs = new List<Song>();
            int finishIndex = playlist.count - 1;

            if (maxResults > 0)
            {
                finishIndex = startIndex + maxResults;

                if (finishIndex > playlist.count - 1)
                {
                    finishIndex = playlist.count - 1;
                }
            }

            for (int index = startIndex; index <= finishIndex; index++)
            {
                Song song = new Song(playlist.get_Item(index));
                songs.Add(song);
            }

            return songs;
        }
    }
}